package com.artislong.config;

import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.artislong.service.OrderService;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.modelcontextprotocol.server.McpServer;
import io.modelcontextprotocol.server.McpServerFeatures;
import io.modelcontextprotocol.server.McpSyncServer;
import io.modelcontextprotocol.server.McpSyncServerExchange;
import io.modelcontextprotocol.server.transport.HttpServletSseServerTransportProvider;
import io.modelcontextprotocol.spec.McpSchema;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;

/**
 * @author 陈敏
 * @version McpServerConfiguration.java, v 1.0 2025 07 06 09:21 chenmin Exp $
 * Created on 2025 07 06
 */
@Configuration
public class McpServerServletConfiguration implements WebMvcConfigurer {

    @Autowired
    private OrderService orderService;

    @Bean
    public HttpServletSseServerTransportProvider servletSseServerTransportProvider() {
        return HttpServletSseServerTransportProvider.builder()
                .objectMapper(new ObjectMapper())
                .baseUrl("/mcp")
                .messageEndpoint("/mcp/message")
                .sseEndpoint("/mcp/sse")
                .build();
    }

    @Bean
    public ServletRegistrationBean<HttpServletSseServerTransportProvider> customHttpSseServerServlet(HttpServletSseServerTransportProvider transportProvider) {
        return new ServletRegistrationBean<>(transportProvider, "/mcp/message", "/mcp/sse");
    }

    @Bean(destroyMethod = "close")
    public McpSyncServer mcpSyncServer(HttpServletSseServerTransportProvider transportProvider) {
        McpSchema.ServerCapabilities capabilities = McpSchema.ServerCapabilities.builder()
                .logging()
                .prompts(true)
                .resources(true, true)
                .tools(true)
                .build();

        // 创建并配置MCP服务器
        McpSyncServer mcpSyncServer = McpServer.sync(transportProvider)
                .serverInfo("my-server", "1.0.0")
                .capabilities(capabilities)
                .build();

        // 添加到工具集中
        mcpSyncServer.addTool(toolSpecification1());
        mcpSyncServer.addTool(toolSpecification2());
        // 添加到提示词集中
        mcpSyncServer.addPrompt(promptSpecification());
        // 添加到资源集中
        mcpSyncServer.addResource(resourceSpecification());

        return mcpSyncServer;
    }

    private McpServerFeatures.SyncToolSpecification toolSpecification1() {
        // 配置工具
        String jsonSchema = """
                {
                	"type":"object",
                	"properties":{
                		"userId" : {
                			"type": "string",
                			"description": "用户ID"
                		},
                		"orderId" : {
                			"type": "string",
                			"description": "订单号"
                		}
                	},
                	"required":[
                	    "userId",
                		"orderId"
                	],
                	"additionalProperties":false
                }
                """;
        // 方法的描述
        McpSchema.Tool tool = new McpSchema.Tool("getOrderDetail", "通过用户ID和订单号获取订单详情信息", jsonSchema);
        // 方法描述对应的执行逻辑
        BiFunction<McpSyncServerExchange, Map<String, Object>, McpSchema.CallToolResult> call = (exchange, arguments) -> {
            OrderService.OrderDetail result = orderService.getOrderDetail(MapUtil.getStr(arguments, "userId"), MapUtil.getStr(arguments, "orderId"));
            return new McpSchema.CallToolResult(JSONObject.toJSONString(result), false);
        };
        // 绑定描述和执行逻辑
        return new McpServerFeatures.SyncToolSpecification(tool, call);
    }
    private McpServerFeatures.SyncToolSpecification toolSpecification2() {
        // 配置工具
        String jsonSchema = """
                {
                	"type":"object",
                	"properties":{
                		"userId" : {
                			"type": "string",
                			"description": "用户ID"
                		}
                	},
                	"required":[
                	    "userId"
                	],
                	"additionalProperties":false
                }
                """;
        // 方法的描述
        McpSchema.Tool tool = new McpSchema.Tool("getOrderDetails", "通过用户ID获取订单列表信息", jsonSchema);
        // 方法描述对应的执行逻辑
        BiFunction<McpSyncServerExchange, Map<String, Object>, McpSchema.CallToolResult> call = (exchange, arguments) -> {
            List<OrderService.OrderDetail> result = orderService.getOrderDetails(MapUtil.getStr(arguments, "userId"));
            return new McpSchema.CallToolResult(JSONObject.toJSONString(result), false);
        };
        // 绑定描述和执行逻辑
        return new McpServerFeatures.SyncToolSpecification(tool, call);
    }

    private McpServerFeatures.SyncPromptSpecification promptSpecification() {

        List<McpSchema.PromptArgument> arguments = new ArrayList<>();
        arguments.add(new McpSchema.PromptArgument("orderId", "订单号", true));

        McpSchema.Prompt prompt = new McpSchema.Prompt("getOrderDetail", "通过订单号获取订单详情信息", arguments);

        BiFunction<McpSyncServerExchange, McpSchema.GetPromptRequest, McpSchema.GetPromptResult> promptHandler = (exchange, request) -> {
            String orderId = MapUtil.getStr(request.arguments(), "orderId");
            List<McpSchema.PromptMessage> messages = new ArrayList<>();
            messages.add(new McpSchema.PromptMessage(McpSchema.Role.ASSISTANT, new McpSchema.TextContent(StrUtil.format("收到的订单编号是：{}", orderId))));
            return new McpSchema.GetPromptResult("请输入订单号", messages);
        };
        return new McpServerFeatures.SyncPromptSpecification(prompt, promptHandler);
    }

    private McpServerFeatures.SyncResourceSpecification resourceSpecification() {
        McpSchema.Annotations annotations = new McpSchema.Annotations(Arrays.asList(McpSchema.Role.USER, McpSchema.Role.ASSISTANT), 0.8);

        McpSchema.Resource resource = new McpSchema.Resource("resource://test", "Test Resource", "A test resource",
                "text/plain", annotations);
        BiFunction<McpSyncServerExchange, McpSchema.ReadResourceRequest, McpSchema.ReadResourceResult> readHandler = (exchange, request) -> {
            List<McpSchema.ResourceContents> contents = new ArrayList<>();
            McpSchema.TextResourceContents resourceContents = new McpSchema.TextResourceContents("resource://test", "text/plain", "Sample resource content");
            contents.add(resourceContents);
            return new McpSchema.ReadResourceResult(contents);
        };
        return new McpServerFeatures.SyncResourceSpecification(resource, readHandler);
    }

}
